#include<iostream>
#include<cstdio>
#include<cstring>
#include<unistd.h>
#include<string>
#include<pthread.h>

#include<memory>
#include"Thread.hpp"

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;//全局
//共享资源，火车票
int tickets = 10000;

// 1. 多个执行流进行安全访问的共享资源 - 临界资源
// 2. 我们把多个执行流中，访问临界资源的代码 -- 临界区 -- 往往是线程代码的很小的一部分
// 3. 想让多个线程串行访问共享资源 -- 互斥
// 4. 对一个资源进行访问的时候，要么不做，要么做完 -- 原子性，不是原子性的情况 -- 一个对资源进行的操作，如果只用一条汇编就能完成 -- 就是原子性。
//    反之，不是原子性。
// 提出解决方案：加锁！

// 就需要尽可能的让多个线程交叉执行
// 多个线程交叉执行的本质：就是让调度器尽可能的频繁发生线程调度与切换
// 线程一般在什么时候发生切换呢？时间片到了，来了更高优先级的线程。线程等待的时候。
// 线程是在什么时候检测上面的问题的呢？从内核态返回用户态的时候，线程要对调度状态进行检测，如果可以，就直接发生线程切换

//加锁的解锁的部分称为临界区：加锁之后明显变慢，因为变成了串行执行
void* getTicket(void* args)
{
    std::string username = static_cast<const char*>(args);
    while(true)
    {
        pthread_mutex_lock(&lock);//加锁
        if(tickets > 0)
        {
            usleep(1234); // 1s = 1000ms = 1000 000us = 1000 000 000 ns
            //值得抢
            std::cout << username << "正在进行抢票 "  << tickets << std::endl;
            //用这段时间来模拟真实的抢票需要花费的时间
           
            tickets--;// 读取数据、更改数据、写回数据
            pthread_mutex_unlock(&lock);
        }
        else
        {
            pthread_mutex_unlock(&lock);
            break;
        }
       
        // 抢完票就完了吗？？
    }
    return nullptr;
}

int main()
{
    std::unique_ptr<Thread> thread1(new Thread(getTicket, (void*)"user1", 1));
    std::unique_ptr<Thread> thread2(new Thread(getTicket, (void*)"user2", 2));
    std::unique_ptr<Thread> thread3(new Thread(getTicket, (void*)"user3", 3));
    std::unique_ptr<Thread> thread4(new Thread(getTicket, (void*)"user4", 4));

    thread1->join();
    thread2->join();
    thread3->join();
    thread4->join();

}


























// // 添加__thread可以将一个内置类型设置为线程局部存储
// __thread int g_val = 100;
// std::string changeId(const pthread_t& thread_id)
// {
//     char tid[128];
//     snprintf(tid, sizeof(tid), "0x%x", thread_id);
//     return tid;
// }


// void* start_routine(void* args)
// {
//     std::string threadname = static_cast<const char*>(args);
//     //pthread_detach(pthread_self()); // 设置自己为分离状态
//     int cnt = 5;
//     while(true)
//     {
//         char tid[6];
//         sleep(1);
//         std::cout << threadname << " running... : " << changeId(pthread_self()) << " g_val: " << g_val << " &g_val: " << &g_val << std::endl;
//         g_val++;
//     }
// }

// int main()
// {
//     pthread_t tid;
//     pthread_create(&tid, nullptr, start_routine, (void*)"thread 1");
//     std::string main_id = changeId(pthread_self());
//     pthread_detach(tid);
//     std::cout << "main thread running ... new thread id: " << changeId(tid) <<std:: endl;

//     sleep(2);
//     //一个线程默认是joinable的，如果设置了分离状态，就不能够进行等待了
//     int n = pthread_join(tid, nullptr);//主线程阻塞式的等待
//     std::cout << "result: " << n << " : " << strerror(n) << std::endl;

//     int cnt = 5;
//     while(true)
//     {
//         char tid[6];
//         sleep(1);
//         std::cout << " main thread running... new thread id: " <<\
//          changeId(pthread_self()) << "main thread id: " << main_id << "g_val: " << g_val << " &g_val: " << &g_val << std::endl;
//     }

//     return 0;
// }